﻿using Autofac;
using Autofac.Core;
using AutoRegistDependency.Enum;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AutoRegistDependency.Extensions
{
    /// <summary>
    /// Autofac定时任务启动类,调用此类的拓展方法可以将job注册并启动 IScheduler
    /// </summary>
    public static class RegisterExtension
    {
        /// <summary>
        /// 注册quartz的job类
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public static void QuartzRegist(this IServiceProvider serviceProvider)
        {
            IComponentContext componentContext = serviceProvider.GetService<IComponentContext>();
            if (componentContext == null)
            {
                throw new InvalidOperationException("WebApplicationBuilder must be build!");
            }

            IScheduler scheduler = componentContext.Resolve<IScheduler>();
            if (scheduler == null)
            {
                throw new InvalidOperationException("QuartzAutofacFactoryModule must be regist!");
            }

            var register = componentContext.Resolve<Register>();
            var componentInfos = register.TypeMapInfo.Values.SelectMany(t => t).Where(t =>
                t.ComponentType == ComponentType.Job && componentContext.IsRegistered(t.InjectType));
            Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>> triggersAndJobs =
                new Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>>();
            foreach (var componentInfo in componentInfos)
            {
                IJobDetail job = JobBuilder.Create(componentInfo.InjectType)
                    .WithIdentity($"{componentInfo.InjectType}_Job")
                    .Build();
                var cronArr = componentInfo.Cron.Split(';');
                var set = new HashSet<ITrigger>();
                for (int i = 0; i < cronArr.Length; i++)
                {
                    ITrigger trigger = TriggerBuilder.Create()
                        .WithIdentity($"{componentInfo.InjectType}_Trigger{i}")
                        .WithCronSchedule(cronArr[i])
                        .WithPriority(componentInfo.Priority)
                        .Build();
                    set.Add(trigger);
                }
                triggersAndJobs.Add(job, set);
            }

            scheduler.ScheduleJobs(triggersAndJobs, true);
            scheduler.Start();
        }
    }
}